package com.lktx.sso.service;

import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hserver.core.ioc.IocUtil;
import cn.hserver.core.ioc.annotation.Autowired;
import cn.hserver.core.ioc.annotation.Bean;
import cn.hserver.core.ioc.annotation.Value;
import cn.hserver.plugin.web.context.HServerContextHolder;
import cn.hserver.plugin.web.interfaces.HttpResponse;
import com.lktx.sso.admin.entity.SsoApp;
import com.lktx.sso.admin.entity.SsoAppJwtConfig;
import com.lktx.sso.admin.entity.SsoUser;
import com.lktx.sso.admin.mapper.SsoUserMapper;
import com.lktx.sso.admin.service.SsoAppJwtConfigService;
import com.lktx.sso.admin.service.SsoAppService;
import com.lktx.sso.admin.service.SsoUserService;
import lombok.extern.slf4j.Slf4j;

import javax.security.auth.login.LoginException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Bean
public class JwtService {

    @Autowired
    private SsoAppService ssoAppService;

    @Autowired
    private SsoUserService ssoUserService;

    @Autowired
    private SsoAppJwtConfigService ssoAppJwtConfigService;

    @Autowired
    private SsoUserMapper ssoUserMapper;

    @Value("oauth.baseIss")
    private String baseIss;


    public void checkLogin(String appId, HttpResponse response) {
        Object loginIdDefaultNull = StpUtil.getLoginIdDefaultNull();
        if (loginIdDefaultNull == null) {
            noLogin(appId, response,"");
        } else {
            yesLogin(appId, response);
        }
    }

    public boolean doLogin(String appId,String clientId, String name, String pwd, HttpResponse response) {
        String message="登录失败";
        try {
            SsoUser login = ssoUserService.login(name, pwd, clientId);
            if (login != null) {
                /**
                 * iss：JWT 签发者
                 * sub：JWT 所面向的用户
                 * aud：接收 JWT 的一方
                 * exp：JWT 的过期时间，这个过期时间必须要大于签发时间
                 * nbf：定义在什么时间之前，该 JWT 都是不可用的
                 * iat：JWT 的签发时间
                 * jti：JWT 的唯一身份标识，主要用来作为一次性 token，从而回避重放攻击
                 */
                Map<String, Object> userInfo = ssoUserMapper.getLoginUserInfo(login.getSsoUserId().toString());
                SaLoginParameter baseLogin = new SaLoginParameter();
                baseLogin.setExtra("iss", String.format("%s/jwt/%s/sso", baseIss, appId));
                userInfo.forEach(baseLogin::setExtra);
                StpUtil.login(login.getSsoUserId(), baseLogin);
                yesLogin(appId, response);
                return true;
            }
        } catch (LoginException e) {
            log.error(e.getMessage(), e);
            message=e.getMessage();
        }
        noLogin(appId, response,message);
        return false;
    }

    public void noLogin(String appId, HttpResponse response,String message) {
        SsoApp ssoApp = ssoAppService.getById(Integer.parseInt(appId));
        Map<String, Object> map = new HashMap<>();
        map.put("appName", ssoApp.getAppName());
        map.put("appIcon", ssoApp.getAppIcon());
        map.put("appId", ssoApp.getSsoAppId());
        map.put("clientId", ssoApp.getClientId());
        map.put("loginUrl", String.format("/jwt/%s/login", appId));
        map.put("message", message);
        response.sendTemplate("jwt_login.ftl", map);
    }


    public void yesLogin(String appId, HttpResponse response) {
        SsoAppJwtConfig jwtConfig = ssoAppJwtConfigService.getById(Integer.valueOf(appId));
        Map<String, Object> map = new HashMap<>();
        map.put("reqType", jwtConfig.getBindingType());
        map.put("token", StpUtil.getTokenValue());
        map.put("redirectUrl", jwtConfig.getRedirectUris());
        if (jwtConfig.getReqKey() == null) {
            jwtConfig.setReqKey("");
        }
        map.put("reqKey", jwtConfig.getReqKey());
        response.sendTemplate("jwt_jump.ftl", map);
    }

}
